package com.smasher.domain.fragment

import android.content.Context
import android.content.DialogInterface
import android.os.Build
import android.os.Bundle
import android.text.TextUtils
import android.view.Gravity
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.RadioGroup
import android.widget.TextView
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.DialogFragment
import com.smasher.core.log.ToastUtil
import com.smasher.domain.R
import com.smasher.domain.databinding.FragmentDomainBinding
import com.smasher.domain.entity.BeanDomain

class DomainFragment : DialogFragment(), View.OnClickListener, RadioGroup.OnCheckedChangeListener {

    private lateinit var mBinding: FragmentDomainBinding
    private var onAddListener: OnAddListener? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setStyle(STYLE_NO_TITLE, 0)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        mBinding = FragmentDomainBinding.inflate(inflater, container, false)
        return mBinding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        mBinding.title.setText(R.string.domain_add)
        mBinding.protocolConfig.setText(R.string.domain_protocol)
        mBinding.protocolHttp.setText(R.string.domain_protocol_http)
        mBinding.protocolHttps.setText(R.string.domain_protocol_https)
        mBinding.ipConfig.setText(R.string.domain_ip)
        mBinding.ipContent.setHint(R.string.add_domain_hint_uri)
        mBinding.portConfig.setText(R.string.domain_port)
        mBinding.portContent.setHint(R.string.add_domain_hint_port)

        mBinding.cancel.setOnClickListener(this)
        mBinding.confirm.setOnClickListener(this)
        mBinding.protocolContent.setOnCheckedChangeListener(this)
    }

    override fun onStart() {
        super.onStart()
        val dialog = dialog
        if (dialog != null) {
            dialog.setCanceledOnTouchOutside(false)
            dialog.setOnKeyListener(keyListener)

            //初始化window相关表现
            val window = dialog.window
            //window.setBackgroundDrawableResource(android.R.color.transparent);
            if (window != null) {
                // 宽度（PX）
                val width = getPrimaryWith(requireContext())
                val params = window.attributes
                params.width = if (width != 0) {
                    (width * 0.9).toInt()
                } else {
                    WindowManager.LayoutParams.MATCH_PARENT
                }
                params.height = WindowManager.LayoutParams.WRAP_CONTENT
                //params.height = (int) (height * 0.8);
                params.gravity = Gravity.CENTER
                //params.horizontalMargin = 0.8f;
                window.attributes = params
            }
        }
    }

    private val keyListener =
        DialogInterface.OnKeyListener { _: DialogInterface?, _: Int, _: KeyEvent? -> false }

    private fun getPrimaryWith(context: Context): Int {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // For API level 30 and above, use WindowMetrics
            val windowMetrics = context.getSystemService(WindowManager::class.java)
                ?.currentWindowMetrics ?: return 0

            val insets = windowMetrics.windowInsets
                .getInsetsIgnoringVisibility(WindowInsetsCompat.Type.systemBars())

            val bounds = windowMetrics.bounds
            bounds.width() - insets.left - insets.right
        } else {
            val displayMetrics = context.resources.displayMetrics
            displayMetrics.widthPixels
        }
    }


    override fun onClick(v: View) {
        val id = v.id
        if (id == R.id.confirm) {
            confirm()
        }
        if (id == R.id.cancel) {
            dismissAllowingStateLoss()
        }
    }


    /**
     *
     * Called when the checked radio button has changed. When the
     * selection is cleared, checkedId is -1.
     *
     * @param group the group in which the checked radio button has changed
     * @param checkedId the unique identifier of the newly checked radio button
     */
    override fun onCheckedChanged(group: RadioGroup?, checkedId: Int) {
        when (checkedId) {
            R.id.protocol_http -> {}
            R.id.protocol_https -> {}
            else -> {}
        }
    }

    /**
     * 生成一个尽量不重复的 Int 值。
     * 该方法利用 System.currentTimeMillis() 获取当前时间的毫秒数，
     * 然后通过位运算获取其低32位，将其转换为 Int 类型返回。
     *
     * @return 一个尽量不重复的 Int 值
     */
    private fun generateUniqueInt(): Int {
        return (System.currentTimeMillis() and 0xFFFFFFFF).toInt()
    }

    private fun confirm() {
        val protocol = when (mBinding.protocolContent.checkedRadioButtonId) {
            R.id.protocol_http -> "http"
            R.id.protocol_https -> "https"
            else -> ""
        }
        if (TextUtils.isEmpty(protocol)) {
            ToastUtil.warning(requireContext(), R.string.domain_tip_ip)
            return
        }
        val host = getEditContent(mBinding.ipContent)
        if (TextUtils.isEmpty(host)) {
            ToastUtil.warning(requireContext(), R.string.domain_tip_ip)
            return
        }
        var port = -1
        val portEditable = getEditContent(mBinding.portContent)
        if (!TextUtils.isEmpty(portEditable)) {
            port = parsePort(portEditable)
        }

        val generateName = "域名" + System.currentTimeMillis()

        val domain = BeanDomain(
            id = generateUniqueInt(),
            name = generateName,
            scheme = protocol,
            host = host,
            port = port
        )

        onAddListener?.let {
            it.onAdd(domain)
            dismissAllowingStateLoss()
        }
    }

    private fun getEditContent(editView: TextView): String {
        val editText = editView.text
        return editText.toString()
    }

    private fun parsePort(portEditable: String): Int {
        var port = -1
        try {
            port = portEditable.toInt()
        } catch (e: NumberFormatException) {
            e.printStackTrace()
        }
        return port
    }

    fun setOnAddListener(onAddListener: OnAddListener?) {
        this.onAddListener = onAddListener
    }

    interface OnAddListener {
        fun onAdd(domain: BeanDomain)
    }

    companion object {

        const val TAG = "Category"

        /**
         * Use this factory method to create a new instance of
         * this fragment using the provided parameters.
         *
         * @return A new instance of fragment CategoryFragment.
         */
        fun newInstance(): DomainFragment {
            return DomainFragment().apply {
                arguments = Bundle()
            }
        }
    }
}
